home *** CD-ROM | disk | FTP | other *** search
/ Libris Britannia 4 / science library(b).zip / science library(b) / DDJMAG / DDJ9207.ZIP / ACOMP.ASC < prev    next >
Text File  |  1992-06-15  |  21KB  |  724 lines

  1. _AUDIO COMPRESSION_
  2. by John W. Ratcliff
  3.  
  4. [LISTING ONE]
  5.  
  6. ;; AC.ASM -> ACOMP assembly language compressor. Written by John W. Ratcliff, 
  7. ;; 1991. Uses Turbo Assembler IDEAL mode and makes HEAVE use of macros. This
  8. ;; algorithm performs an exhaustive search for the best delta mod for each 
  9. ;; section of the waveform. It is very CPU intensive, and the algorithm can
  10. ;; be a little difficult to follow in assembly language.
  11.  
  12.     IDEAL           ; Enter Turbo Assembler's IDEAL mode.
  13.     JUMPS           ; Allow automatic jump sizing.
  14.     INCLUDE "prologue.mac"  ; Include usefull assembly lanugage macro file.
  15.  
  16. SEGMENT _TEXT   BYTE PUBLIC 'CODE'
  17.     ASSUME  CS:_TEXT
  18. ;; This macro computes the amount of error in a frame of data, at this
  19. ;; bit resolution and this delta mod location.
  20. Macro   DoError BITS
  21.     LOCAL   @@NO
  22.     mov bx,[COMP]       ; Current delta mod value.
  23.     mov bh,BITS         ; Current bit resolution.
  24.     push    [MINERR]        ; Pass minimum error so far.
  25.     push    [PREV]          ; Pass previous data point.
  26.     call    ComputeError        ; Compute error for frame.
  27.     add sp,4            ; Balance stack.
  28.     cmp dx,[MINERR]     ; Less than previous minimum?
  29.     jge @@NO            ; no, don't update.
  30.     mov [MINERR],dx     ; Save as new miniume
  31.     mov [BESTPREV],ax       ; Best previous location.
  32.     xor ah,ah           ;
  33.     mov al,bl           ; Get best delta modution.
  34.     mov [BEST1],ax      ; save it.
  35.     mov al,bh           ; Get best bits.
  36.     mov [BEST2],ax      ; Save it.
  37. @@NO:
  38.     endm
  39.  
  40. SQLCH   equ 64      ; Squelch bit.
  41. RESYNC  equ 128     ; Resynchronization bit.
  42.  
  43. DELTAMOD equ    00110000b   ; Bit mask for delta mod bits.
  44.  
  45. ONEBIT  equ 00010000b   ; Bit pattern for one bit delta mod.
  46. TWOBIT  equ 00100000b   ; Bit pattern for two bit delta mod.
  47. FOURBIT equ 00110000b   ; Bit pattern for two bit delta mod.
  48.  
  49. ;; This macro echos a message to the text screen, so that we can
  50. ;; monitor the progress of the compression algorithm.
  51. Macro   Note    MSG
  52.     push    ax
  53.     lea ax,[MSG]
  54.     push    ax
  55.     call    Notify
  56.     add sp,2
  57.     pop ax
  58.     endm
  59.  
  60.     public  _CompressAudio
  61. ;;This the the ACOMP compression procedure.
  62. ;;int far CompressAudio(unsigned char far *shand, 
  63. ;;                                           Address of audio data to compress.
  64. ;;          unsigned char far *dhand, 
  65. ;;                                      Destination address of compressed data.
  66. ;;          unsigned int slen, Length of audio data to compress.
  67. ;;          int squelch,       Squelch value allowed.
  68. ;;          int freq,      Playback frequency of audio data.
  69. ;;          int frame,     Frame size.
  70. ;;          int maxerr);       Maximum error allowed.
  71. Proc    _CompressAudio  far
  72.         ARG     SHAN:DWORD,DHAN:DWORD,SLEN:WORD,SQUELCH:WORD,FREQ:WORD,
  73.                                                          FRAME:WORD,MAXERR:WORD
  74.     LOCAL   PREV:WORD,COMP:WORD,MINERR:WORD,BEST1:WORD,BEST2:
  75.                                                 WORD,BESTPREV:WORD = LocalSpace
  76.     PENTER  LocalSpace
  77.     PushCREGS
  78.  
  79.     lds si,[SHAN]       ; Get source address.
  80.     les di,[DHAN]       ; Get destination address.
  81.     mov cx,[SLEN]       ; Get length of audio data.
  82.  
  83.     mov ax,cx       ; Get length of audio sample into AX
  84.     stosw           ; Store it.
  85.     mov ax,[FREQ]   ; Get frequency of recording.
  86.     stosw           ; Store it.
  87.     mov ax,[FRAME]  ; Get the frame size.
  88.     stosb           ; Store it.
  89.     mov ax,[SQUELCH]    ; Get squelch size
  90.     stosb           ; Store it.
  91.     mov ax,[MAXERR] ; Get maximum error allowed.
  92.     stosw           ; Save it.
  93.     xor ax,ax
  94.     lodsb           ; Get first data sample
  95.     mov [PREV],ax
  96.     stosb           ; Store first data sample.
  97.     dec cx      ; Decrement sample size count.
  98.     jz  @@DONE
  99.  
  100. @@SQU:  mov ah,0Bh      ; Test keyboard status.
  101.     int 21h
  102.     or  al,al
  103.     jz  @@NOK
  104.     mov ah,08h      ; If a key was pressed get that key
  105.     int 21h     ; value, and see if it was the
  106.     cmp al,27       ; escape key.
  107.     jne @@NOK
  108.     xor ax,ax       ; If escape, return to caller, with abort.
  109.     jmp @@EXIT
  110. @@NOK:
  111.     xor ax,ax
  112.     mov dx,[SQUELCH]    ; Get squelch value.
  113.     push    cx      ; Save remaining data count.
  114.     push    si      ; Save si.
  115. @@CK1:  lodsb           ; Get data byte.
  116.     sub ax,[PREV]   ; Difference from previous data sample?
  117.     jns @@CK2       ; if positive leave it alone.
  118.     neg ax      ; Make it positive.
  119. @@CK2:  cmp ax,dx       ; Is it within the squelch range?
  120.     jg  @@NOS       ; yes, keep checking!
  121.     loop    @@CK1       ; Keep going.
  122.     inc si      ; Plus one, this last one counts.
  123. @@NOS:  pop ax      ; Get back start SI
  124.     mov dx,si       ; DX contains current address.
  125.     sub dx,ax       ; Compute number of squelch bytes encountered.
  126.     dec dx      ; Less, last non squelch byte.
  127.     cmp dx,3        ; At least three?
  128.     jle @@NOSQ      ; no, don't squelch it.
  129. @@SQS:  cmp dx,63       ; Is it under 63?
  130.     jle @@SEND
  131.     mov ax,(63 + SQLCH)  ; Send count.
  132.     sub dx,63       ; Less the 63 count we just sent.
  133.     stosb           ; Write squelch byte out.
  134.     jmp short @@SQS     ; Continue.
  135. @@SEND: mov ax,dx       ; Get remaining count.
  136.     or  ax,SQLCH    ; Or squelch bit on.
  137.     stosb           ; Send squelch count out.
  138.     dec si      ; Back up to last data point.
  139.     pop ax      ; Pull CX off of stack, use current count.
  140.     Note    msg0
  141.     jmp short @@NXT
  142. @@NOSQ: mov si,ax       ; Replace where source was.
  143.     pop cx      ; Get back remaining data count.
  144.  
  145. @@NXT:  jcxz    @@DONE      ; Exit if done.
  146.     cmp cx,[FRAME]  ; Below current frame size?
  147.     jae @@GO        ; no, go ahead.
  148. @@FIN:  lodsb           ; Get raw sample.
  149.     shr al,1        ; Down to closest aproximated value.
  150.     or  al,RESYNC   ; Add resync bit to it.
  151.     stosb           ; Store out.
  152.     loop    @@FIN       ; Keep sending final bytes.
  153.     jmp @@DONE      ; exit, after sending final bytes.
  154.  
  155. @@GO:   mov [MINERR],07FFFh
  156.     push    cx
  157.     mov cx,[FRAME]  ; Set CX to frame size.
  158.  
  159.     mov [COMP],1
  160. @@ALL1: DoError 1       ; Try one bit mode, +/-1.
  161.     inc [COMP]
  162.     cmp [COMP],17   ; Try delta comp values clean up to 16!!
  163.     jne @@ALL1
  164.  
  165.     mov ax,[MINERR]
  166.     cmp ax,[MAXERR]
  167.     jle @@BCMP      ; Not good enough...
  168.     mov [COMP],1
  169. @@ALL2: DoError 2       ; Try two bit mode, +/-1.
  170.     inc [COMP]
  171.     cmp [COMP],17   ; Try delta comp values clean up to 16!!
  172.     jne @@ALL2
  173.  
  174.     mov ax,[MINERR]
  175.     cmp ax,[MAXERR]
  176.     jle @@BCMP
  177.     mov [COMP],1
  178. @@ALL4: DoError 8       ; Try four bit mode, +/-1.
  179.     inc [COMP]
  180.     cmp [COMP],17   ; Try delta comp values clean up to 16!!
  181.     jne @@ALL4
  182.  
  183.     mov ax,[MINERR] ; Get what the minimum error was.
  184.     cmp ax,[MAXERR] ; Minimum error > maximum error?
  185.     jle @@BCMP      ; no, then send frame.
  186.     pop cx      ; Get back CX
  187.     lodsb           ; Get data sample.
  188.     and al,(NOT 1)  ; Strip off bottom bit.
  189.     xor ah,ah
  190.     mov [PREV],ax   ; New previous.
  191.     shr al,1        ; /2
  192.     or  al,RESYNC   ; Or resync bit on.
  193.     stosb           ; Store it out into data stream.
  194.     Note    msg1
  195.     loop    @@SQU       ; Go check squelching.
  196.     jmp @@DONE      ; Done, if this was last data sample.
  197. @@BCMP: mov bx,[BEST1]  ; Get best comp.
  198.     mov ax,[BEST2]  ; Get best bit size.
  199.     mov bh,al       ; Into BH
  200.     mov ax,32000
  201.     push    ax
  202.     push    [PREV]      ; Pass prev.
  203.     call    ComputeError    ; Re-compute error term.
  204.     add sp,4
  205.     mov [PREV],ax   ; New previous.
  206. ;; Now time to store results!
  207.     mov bx,[BEST1]  ; Get best comp.
  208.     cmp [BEST2],1   ; 1 bit?
  209.     jne @@NXT1
  210.     call    Fold1Bit    ; Fold 1 bit data.
  211.     Note    msg2
  212.     jmp short @@IN      ; Reenter.
  213. @@NXT1: cmp [BEST2],2   ; 2 bit data?
  214.     jne @@NXT2
  215.     call    Fold2Bit
  216.     Note    msg3
  217.     jmp short @@IN
  218. @@NXT2:
  219.     call    Fold4Bit
  220.     Note    msg4
  221. @@IN:   mov ax,[FRAME]
  222.     pop cx      ; Get back CX
  223.     add si,ax       ; Advance source
  224.     sub cx,ax       ; Decrement data count.
  225.     jnz @@SQU       ; Continue, if not at end.
  226.  
  227. @@DONE:
  228.     mov ax,di       ; Size of compressed file.
  229.     les di,[DHAN]
  230.     sub ax,di       ; Difference.
  231.  
  232. @@EXIT:
  233.     PopCREGS
  234.     PLEAVE
  235.     ret
  236.     endp
  237.  
  238. ;; Compute error:  Registers on entry are:
  239. ;;         DS:SI -> source data.
  240. ;;         CX    -> number of bytes to compute error term in.
  241. ;;         DX    -> total error incurred.
  242. ;;         BL    -> delta comp size.
  243. ;;         BH    -> maximum bit size value, positive or negative.
  244. ;; Exit: CX,DS:SI stay the same.
  245. ;;   DX -> total error term.
  246. ;;   AX -> new previous.
  247. Proc    ComputeError    near
  248.     ARG PREV:WORD,MINERR:WORD
  249.     LOCAL   CUR:WORD = LocalSpace
  250.     PENTER  LocalSpace
  251.  
  252.     push    cx
  253.     push    si
  254.     push    di      ; Save destination address.
  255.     xor dx,dx       ; Initally no error.
  256.  
  257. @@CERR: lodsb           ; Get a data byte.
  258.     xor ah,ah       ; Zero high byte.
  259.     mov [CUR],ax    ; Save as current sample.
  260.     sub ax,[PREV]
  261.     cmp bl,1
  262.     je  @@ND
  263.     idiv    bl      ; Divided by delta mod size.
  264. @@ND:   or  al,al
  265.     js  @@DON       ; Do negative side.
  266.     jnz @@CNT       ; If not zero then continue.
  267.     inc al      ; Can't represent a zero, make it one.
  268. @@CNT:  cmp al,bh       ; > max representative size?
  269.     jle @@OK        ; no, it fit as is.
  270.     mov al,bh       ; Make it the max representative size.
  271.     jmp short @@OK      ;
  272. @@DON:  neg al      ; Make it positive.
  273.     cmp al,bh       ; > max representative size?
  274.     jbe @@K2        ; no, use it.
  275.     mov al,bh       ; Make it the max representative size.
  276. @@K2:   neg al      ; Make it negative again.
  277. @@OK:
  278.     stosb           ; Store data value out.
  279.     imul    bl      ; Times delta comp value.
  280.     add ax,[PREV]   ; Add to previous data point.
  281.     js  @@CS        ; Do signed case.
  282.     cmp ax,255      ; Did it over flow?
  283.     jle @@K3        ; No, then it fit byte sized.
  284.     mov ax,255      ; Make it byte sized.
  285.     jmp short @@K3      ; Re-enter
  286. @@CS:   xor ax,ax       ; Close as we can get, underflow.
  287. @@K3:   mov [PREV],ax   ; This is our new aproximated value.
  288.     sub ax,[CUR]    ; Less actual value.
  289.     jns @@K4        ; if positive then fine.
  290.     neg ax      ; Take absolute value.
  291. @@K4:   add dx,ax       ; Add into total error.
  292.     cmp dx,[MINERR] ; Greater than minimum error allowed?
  293.     jg  @@OUT
  294.     loop    @@CERR
  295. @@OUT:  mov ax,[PREV]   ; Current previous data point.
  296.     pop di      ; Restore destination address.
  297.     pop si      ; Reset SI back to start.
  298.     pop cx      ; Reset CX back to start.
  299.     PLEAVE
  300.     ret
  301.     endp
  302. Macro   BuildByte
  303.     LOCAL   @@HOP1,@@HOP2
  304.     lodsb
  305.     or  al,al       ; Is it signed?
  306.     jns @@HOP1
  307.     shl ah,1        ; Rotate.
  308.     jmp short @@HOP2
  309. @@HOP1: stc
  310.     rcl ah,1
  311. @@HOP2:
  312.     endm
  313. ;; Fold 1 bit data.
  314. ;; ES:DI -> points to data ready to fold out.
  315. ;; CX-> frame size.
  316. ;; BL-> contains delta size.
  317. Proc    Fold1Bit    near
  318.     push    ds
  319.     push    si
  320.     push    di      ; Header byte address.
  321.     push    es
  322.     pop ds      ; DS=ES
  323.     mov si,di       ; Source and dest.
  324.     inc di      ; skip past header byte.
  325. @@FOLD: xor ah,ah       ; Dest byte to be built, zero it.
  326.     BuildByte
  327.     BuildByte
  328.     BuildByte
  329.     BuildByte
  330.     BuildByte
  331.     BuildByte
  332.     BuildByte
  333.     BuildByte
  334.     mov al,ah
  335.     stosb           ; Store it out.
  336.     sub cx,8        ; Less the 8 samples just folded up.
  337.     jnz @@FOLD      ; Continue.
  338.  
  339.     pop si      ; Get back header byte address.
  340.     mov al,bl       ; Get delta comp size.
  341.     dec al      ; Less one.
  342.     or  al,ONEBIT   ; Or the One Bit mode flag on.
  343.     mov [ds:si],al  ; Store header byte.
  344.  
  345.     pop si
  346.     pop ds
  347.     ret
  348.     endp
  349.  
  350. ;; 2 Bit Format:  00 -> -2
  351. ;;        01 -> -1
  352. ;;        10 -> +1
  353. ;;        11 -> +2
  354. Macro   BByte
  355.     LOCAL   @@HOP1,@@HOP2
  356.     lodsb
  357.     or  al,al       ; Is it signed?
  358.     jns @@HOP1
  359.     add al,2        ; Adjust it.
  360.     jmp short @@HOP2
  361. @@HOP1: inc al      ; Plus 1 to fit into format size.
  362. @@HOP2: shl ah,1
  363.     shl ah,1
  364.     or  ah,al       ; Place bits into byte being built.
  365.     endm
  366. ;; Fold 2 bit data.
  367. ;; ES:DI -> points to data ready to fold out.
  368. ;; CX-> frame size.
  369. ;; BL-> contains delta size.
  370. Proc    Fold2Bit    near
  371.     push    ds
  372.     push    si
  373. @@F2:
  374.     push    di      ; Header byte address.
  375.  
  376.     push    es
  377.     pop ds      ; DS=ES
  378.     mov si,di       ; Source and dest.
  379.     inc di      ; skip past header byte.
  380. @@FOLD: xor ah,ah       ; Dest byte to be built, zero it.
  381.     BByte
  382.     BByte
  383.     BByte
  384.     BByte
  385.     mov al,ah
  386.     stosb           ; Store it out.
  387.     sub cx,4        ; Folded up 4 samples.
  388.     jnz @@FOLD      ; Continue.
  389.  
  390.     pop si      ; Get back header byte address.
  391.     mov al,bl       ; Get delta comp size.
  392.     dec al      ; Less one.
  393.     or  al,TWOBIT   ; Or the One Bit mode flag on.
  394.     mov [ds:si],al  ; Store header byte.
  395.  
  396.     pop si
  397.     pop ds
  398.     ret
  399.     endp
  400. ;; Four bit format:
  401. ;; 0 -> -8
  402. ;; 1 -> -7
  403. ;; 2 -> -6
  404. ;; 3 -> -5
  405. ;; 4 -> -4
  406. ;; 5 -> -3
  407. ;; 6 -> -2
  408. ;; 7 -> -1
  409. ;; 8 -> +1
  410. ;; 9 -> +2
  411. ;;10 -> +3
  412. ;;11 -> +4
  413. ;;12 -> +5
  414. ;;13 -> +6
  415. ;;14 -> +7
  416. ;;15 -> +8
  417. Macro   Adjust4bit
  418.     LOCAL   @@HOP1,@@HOP2
  419.     lodsb
  420.     or  al,al
  421.     jns @@HOP1
  422.     add al,8        ; Adjust it.
  423.     jmp short @@HOP2
  424. @@HOP1: add al,7        ; Adjust it.
  425. @@HOP2:
  426.     endm
  427. ;; Fold 4 bit data.
  428. ;; ES:DI -> points to data ready to fold out.
  429. ;; CX-> frame size.
  430. ;; BL-> contains delta size.
  431. Proc    Fold4Bit    near
  432.     push    ds
  433.     push    si
  434.  
  435.     push    di      ; Header byte address.
  436.  
  437.     push    es
  438.     pop ds      ; DS=ES
  439.     mov si,di       ; Source and dest the same.
  440.     inc di      ; skip past header byte.
  441. @@FOLD: Adjust4bit      ; Get first sample.
  442.     ShiftL  al,4        ; Into high nibble.
  443.     mov ah,al       ; Into AH
  444.     Adjust4bit      ; Get next nibble.
  445.     or  al,ah       ; One whole byte.
  446.     stosb           ; Store it out.
  447.     sub cx,2        ; Folded up 4 samples.
  448.     jnz @@FOLD      ; Continue.
  449.  
  450.     pop si      ; Get back header byte address.
  451.     mov al,bl       ; Get delta comp size.
  452.     dec al      ; Less one.
  453.     or  al,FOURBIT  ; Or the One Bit mode flag on.
  454.     mov [ds:si],al  ; Store header byte.
  455.  
  456.     pop si
  457.     pop ds
  458.     ret
  459.     endp
  460. msg0    db  "SQUELCH"
  461. msg1    db  "RESYNC "
  462. msg2    db  "1 BIT  "
  463. msg3    db  "2 BIT  "
  464. msg4    db  "4 BIT  "
  465.  
  466. Proc    Notify  near
  467.     ARG MSG:WORD
  468.     PENTER  0
  469.     PushAll
  470.  
  471.     push    cs
  472.     pop ds
  473.     mov ax,0B800h
  474.     mov es,ax
  475.     mov si,[MSG]
  476.     xor di,di
  477.     mov ah,1Fh
  478.     mov cx,7
  479. @@SND:  lodsb
  480.     stosw
  481.     loop    @@SND
  482.  
  483.     PopAll
  484.     PLEAVE
  485.     ret
  486.     endp
  487.  
  488.     ENDS
  489.     END
  490.  
  491.  
  492.  
  493. [LISTING TWO]
  494.  
  495. ;; UC.ASM        -> Uncompress ACOMP compressed audio data.
  496. ;;               Written by John W. Ratcliff, 1991.
  497. ;;               Uses Turbo Assembler IDEAL mode.
  498.  
  499.     IDEAL        ; Enter Turbo Assembler IDEAL mode.
  500.     JUMPS        ; Allow automatic jump sizing.
  501.  
  502.     INCLUDE "prologue.mac"  ; Include common useful assembly macros.
  503.  
  504. SMALL_MODEL    equ    0   ;: true only if trying to generate near calls
  505.  
  506.     SETUPSEGMENT            ; Setup _TEXT segment.
  507.  
  508. Macro    CPROC    name
  509.     public    _&name
  510. IF    SMALL_MODEL
  511. Proc    _&name    near
  512. ELSE
  513. Proc    _&name    far
  514. ENDIF
  515.     endm
  516.  
  517. SQLCH    equ    64        ; Squelch byte flag
  518. RESYNC    equ    128        ; Resync byte flag.
  519.  
  520. DELTAMOD equ    00110000b    ; Bit mask for delta mod bits.
  521.  
  522. ONEBIT    equ    00010000b    ; Bit pattern for one bit delta mod.
  523. TWOBIT    equ    00100000b    ; Bit pattern for two bit delta mod.
  524. FOURBIT equ    00110000b    ; Bit pattern for two bit delta mod.
  525.  
  526.  
  527. base    dw    ?        ; Base address inside translate table.
  528.  
  529.  
  530. TRANS    db    -8,-7,-6,-5,-4,-3,-2,-1,1,2,3,4,5,6,7,8
  531.     db    -16,-14,-12,-10,-8,-6,-4,-2,2,4,6,8,10,12,14,16
  532.     db    -24,-21,-18,-15,-12,-9,-6,-3,3,6,9,12,15,18,21,24
  533.     db    -32,-28,-24,-20,-16,-12,-8,-4,4,8,12,16,20,24,28,32
  534.     db    -40,-35,-30,-25,-20,-15,-10,-5,5,10,15,20,25,30,35,40
  535.     db    -48,-42,-36,-30,-24,-18,-12,-6,6,12,18,24,30,36,42,48
  536.     db    -56,-49,-42,-35,-28,-21,-14,-7,7,14,21,28,35,42,49,56
  537.     db    -64,-56,-48,-40,-32,-24,-16,-8,8,16,24,32,40,48,56,64
  538.     db    -72,-63,-54,-45,-36,-27,-18,-9,9,18,27,36,45,54,63,72
  539.     db    -80,-70,-60,-50,-40,-30,-20,-10,10,20,30,40,50,60,70,80
  540.     db    -88,-77,-66,-55,-44,-33,-22,-11,11,22,33,44,55,66,77,88
  541.     db    -96,-84,-72,-60,-48,-36,-24,-12,12,24,36,48,60,72,84,96
  542.     db    -104,-91,-78,-65,-52,-39,-26,-13,13,26,39,52,65,78,91,104
  543.     db    -112,-98,-84,-70,-56,-42,-28,-14,14,28,42,56,70,84,98,112
  544.     db    -120,-105,-90,-75,-60,-45,-30,-15,15,30,45,60,75,90,105,120
  545.     db    -128,-112,-96,-80,-64,-48,-32,-16,16,32,48,64,80,96,112,127
  546.  
  547. CPROC    GetFreq         ; Report playback frequency for an ACOMP file.
  548.     ARG    SOURCE:DWORD
  549.     PENTER    0
  550.     push    es
  551.     les    bx,[SOURCE]
  552.     mov    ax,[es:bx+2]
  553.     pop    es
  554.     PLEAVE
  555.     ret
  556.     endp
  557.  
  558. ;; DX contains PREVIOUS.
  559. ;; AH contains bit mask being rotated out.
  560. ;; BX up/down 1 bit value.
  561. Macro    Delta1
  562.     LOCAL    @@UP,@@STORE
  563.     shl    ah,1    ; Rotate bit mask out.
  564.     jc    @@UP
  565.     sub    dx,bx
  566.     jns    @@STORE
  567.     xor    dx,dx    ; Zero it out.
  568.     jmp short @@STORE
  569. @@UP:    add    dx,bx
  570.     or    dh,dh
  571.     jz    @@STORE
  572.     mov    dx,255
  573. @@STORE:mov    al,dl        ; Store result.
  574.     stosb
  575.     endm
  576.  
  577. ;; BX-> base address of translate table.
  578. ;; DX-> previous.
  579. ;; AL-> index.
  580. Macro    DeModulate
  581.     LOCAL    @@HIGH,@@OK
  582.     xlat    [cs:bx] ; Translate into lookup table.
  583.     cbw        ; Make it a signed word.
  584.     add    dx,ax    ; Do word sized add, into previous.
  585.     jns    @@HIGH
  586.     xor    dx,dx    ; Underflowed.
  587. @@HIGH: or    dh,dh    ; Did it overflow?
  588.     jz    @@OK
  589.     mov    dx,255    ; Maxed out.
  590. @@OK:    mov    al,dl
  591.     stosb
  592.     endm
  593.  
  594.  
  595. ;;unsigned int      far UnCompressAudio(unsigned char far *source,unsigned char far *dest);
  596. ;; UnCompressAudio will decompress data which was compressed using ACOMP
  597. ;; into the destination address provided.  UnCompressAudio returns the
  598. ;; total size, in bytes, of the uncompressed audio data.
  599. CPROC    UnCompressAudio
  600.     ARG    SHAN:DWORD,DHAN:DWORD
  601.     LOCAL    SLEN:WORD,FREQ:WORD,FRAME:WORD,BITS:WORD = LocalSpace
  602.     PENTER    LocalSpace
  603.     PushCREGS
  604.  
  605.     lds    si,[SHAN]        ; Get source segment
  606.     les    di,[DHAN]        ; Get destination segment
  607.  
  608.     lodsw                ; Get length.
  609.     mov    [SLEN],ax        ; Save length.
  610.     mov    cx,ax            ; Into CX
  611.     lodsw                ; Frequency.
  612.     mov    [FREQ],ax        ; Save frequency
  613.     lodsb                ; Get frame size.
  614.     xor    ah,ah            ; Zero high byte
  615.     mov    [FRAME],ax        ; Save it.
  616.     lodsb                ; Get squelch, and skip it.
  617.     lodsw                ; Get maximum error, and skip it.
  618.     lodsb                ; Get initial previous data point.
  619.     stosb                ; Store it.
  620.     xor    ah,ah            ; zero high byte.
  621.     mov    dx,ax        ; Save into previous word.
  622.     dec    cx        ; Decrement total by one.
  623.     jz    @@DONE        ; Exit
  624.     mov    ah,al        ; AH, always the previous.
  625. @@DCMP: lodsb            ; Get sample.
  626.     test    al,RESYNC    ; Resync byte?
  627.     jz    @@NOTR        ; no, skip.
  628.     shl    al,1        ; Times two.
  629.     mov    dl,al        ; Into previous.
  630.     xor    dh,dh        ; Zero high word.
  631.     stosb            ; Store it.
  632.     loop    @@DCMP        ; Next one.
  633.     jmp    @@DONE
  634.  
  635. @@NOTR: test    al,SQLCH    ; Squelch byte?
  636.     jz    @@FRAM        ; no, then it is a frame.
  637.     and    al,00111111b    ; Leave just the count.
  638.     push    cx        ; Save current countdown counter.
  639.     mov    cl,al        ; get repeat count
  640.     xor    ch,ch        ; zero high byte of CX
  641.     mov    bx,cx        ; Repeat count in DX
  642.     mov    al,dl        ; Repeat of previous.
  643.     rep    stosb        ; Repeat it.
  644.     pop    cx        ; Get back remaining count.
  645.     sub    cx,bx        ; Less.
  646.     jnz    @@DCMP        ; Keep going.
  647.     jmp    @@DONE
  648.  
  649. @@FRAM:
  650.     mov    bx,ax        ; command byte into BX
  651.     and    bx,0Fh        ; Multiplier being used.
  652.     ShiftL    bx,4        ; Times 16.
  653.     add    bx,offset TRANS ; Plus address of translate table.
  654.     and    al,DELTAMOD    ; Leave just delta mod.
  655.     push    cx
  656.     mov    cx,[FRAME]    ; Get frame size.
  657.     cmp    al,ONEBIT    ; In one bit delta mod?
  658.     jne    @@NEXT1     ; no, try other.
  659.     ShiftR    cx,3        ; /8
  660.     mov    bl,[cs:bx+8]    ; Get up amount
  661.     xor    bh,bh        ; Zero high byte.
  662. @@GO:    lodsb
  663.     xchg    al,ah        ; Place prev in AL, Bit mask in AH
  664.     Delta1
  665.     Delta1
  666.     Delta1
  667.     Delta1
  668.     Delta1
  669.     Delta1
  670.     Delta1
  671.     Delta1
  672.     mov    ah,al
  673.     loop    @@GO
  674.     jmp    @@RENTER
  675.  
  676. @@NEXT1:cmp    al,TWOBIT    ; In two bit delta mod mode?
  677.     jne    @@NEXT2
  678.     add    bx,6        ; Point at +- 2 bit's in table.
  679.     shr    cx,1
  680.     shr    cx,1        ; 4 samples per byte.
  681. @@GOGO: lodsb
  682.     ShiftR    al,6
  683.     DeModulate
  684.     mov    al,[ds:si-1]
  685.     ShiftR    al,4
  686.     and    al,3
  687.     DeModulate
  688.     mov    al,[ds:si-1]
  689.     ShiftR    al,2
  690.     and    al,3
  691.     DeModulate
  692.     mov    al,[ds:si-1]
  693.     and    al,3
  694.     DeModulate
  695.     loop    @@GOGO
  696.     jmp short @@RENTER
  697. @@NEXT2:shr    cx,1        ; Two samples per byte.
  698. @@GO2:    lodsb            ; Get sample.
  699.     ShiftR    al,4
  700.     DeModulate
  701.     mov    al,[ds:si-1]
  702.     and    al,0Fh
  703.     DeModulate
  704.     loop    @@GO2
  705.  
  706. @@RENTER:
  707.     pop    cx
  708.     sub    cx,[FRAME]
  709.     jnz    @@DCMP        ; Continue decompress
  710.  
  711. @@DONE:
  712.     mov    ax,[SLEN]    ; Uncompressed length.
  713.  
  714.     PopCREGS
  715.     PLEAVE
  716.     ret
  717.     endp
  718.  
  719.  
  720.     ENDS
  721.     END
  722.  
  723.  
  724.